package cn.antblog.thread;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author yangjy
 * @version 1.0
 * @description: TODO
 * @date 2022/8/24 15:25
 */
public class ReadFile {

    public AtomicInteger index = new AtomicInteger(0);

    public long size;

    public int buffer_size;
    /**
     * 可以自由访问文件的任意位置。
     * 允许自由定位文件记录指针。
     * 只能读写文件而不是流。
     */
    RandomAccessFile orign_raf;
    RandomAccessFile target_raf;
    FileChannel orignFileChannel;
    FileChannel targetFileChannel;

    public ReadFile(File orign, int buffer_size) throws FileNotFoundException {
        /**
         * mode – 访问模式
         * ➢ "r"：以只读方式打开指定文件。如果试图对该RandomAccessFile执行写入方法，都将抛出IOException异常。
         * ➢ "rw"：以读、写方式打开指定文件。如果该文件尚不存在，则尝试创建该文件。
         * ➢ "rws"：以读、写方式打开指定文件。相对于"rw"模式，还要求对文件的内容或元数据的每个更新都同步写入到底层存储设备。
         * ➢ "rwd"：以读、写方式打开指定文件。相对于"rw"模式，还要求对文件内容的每个更新都同步写入到底层存储设备。
         */
        RandomAccessFile orign_raf = new RandomAccessFile(orign, "rw");
        //RandomAccessFile target_raf = new RandomAccessFile(target, "rw");
        this.orignFileChannel = orign_raf.getChannel();
        //this.targetFileChannel = target_raf.getChannel();
        this.buffer_size = buffer_size;
        this.size = orign.length();
        System.out.println("构造完毕");
    }


    class ReadTask implements Runnable {
        @Override
        public void run() {
            // 这个任务中需要使用cas获取到当前的 index，并且读取index+buffer值，然后将index改为
            int cur_index;
            System.out.println("执行");
            while ((cur_index = index.get()) < size) {

                int target_index = (cur_index + buffer_size) > size ? (int) size : cur_index + buffer_size;


                if (index.compareAndSet(cur_index, target_index + 1)) {
                    //如果cas 成功就进行读写操作

                    System.out.println(Thread.currentThread().getName() + "读取了cur_index" + cur_index + "到" + target_index + "的缓冲数据");
                    byte[] content = readFile(cur_index, target_index);

                    // 读取到了内容可以在下面进行一些别的处理操作

                }
            }

        }

        public byte[] readFile(int orign_index, int target_index) {

            // 读取文件,使用一个map内存映射进行读取，可以加速读取吧
            MappedByteBuffer map;
            byte[] byteArr = new byte[target_index - orign_index];
            try {
                map = orignFileChannel.map(FileChannel.MapMode.READ_ONLY, orign_index, target_index - orign_index);

                map.get(byteArr, 0, target_index - orign_index);
            } catch (Exception e) {
                System.out.println("读取" + orign_index + "到" + target_index + "失败");
                e.printStackTrace();
            }
            return byteArr;


        }


    }

    class WriteTask implements Runnable {

        @Override
        public void run() {

            byte[] a = new byte[1024];
            int cur_index;
            System.out.println("执行");
            while ((cur_index = index.get()) < size) {

                int target_index = (cur_index + buffer_size) > size ? (int) size : cur_index + buffer_size;


                if (index.compareAndSet(cur_index, target_index + 1)) {
                    //如果cas 成功就进行读写操作
                    //成功
                    System.out.println(Thread.currentThread().getName() + "写了cur_index" + cur_index + "到" + target_index + "的缓冲数据");
                    writeFile(cur_index, target_index, a);

                    // 读取

                }
            }
        }

        public void writeFile(int orign_index, int target_index, byte[] content) {
            //然后进行写
            // 读取文件,使用一个map内存映射进行读取，可以加速读取吧
            MappedByteBuffer map;
            byte[] byteArr = new byte[target_index - orign_index];
            try {
                map = targetFileChannel.map(FileChannel.MapMode.READ_ONLY, orign_index, target_index - orign_index);

                map.position();
                map.put(content);
            } catch (IOException e) {
                e.printStackTrace();
            }


        }
    }

    public static void main(String[] args) throws FileNotFoundException {

        File orign = new File("C:\\Users\\YangJingyi\\Desktop\\hh_per_prod_017_dm_ddetail_sale_result_03.csv");
        ReadFile pf = new ReadFile(orign, 30);
        ThreadPoolExecutor poll = new ThreadPoolExecutor(4,
                5,
                1,
                TimeUnit.HOURS,
                new LinkedBlockingDeque<>(10));

        for (int i = 0; i < 5; i++) {
            poll.execute(pf.new ReadTask());
        }


    }

}
